package grape.auth.rest.service.impl;

import grape.base.rest.client.user.UserClient;
import grape.base.service.user.dto.UserInnerDetailDto;
import grape.base.service.user.po.UserIdentifier;
import grape.common.AbstractLoginUser;
import grape.common.service.common.dataconstraint.RawDataConstraint;
import grape.common.service.loginuser.LoginUser;
import grape.common.tools.ToolService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created by yangwei
 * Created at 2020/9/2 17:12
 */
public abstract class BaseUserDetailsServiceImpl implements UserDetailsService, ToolService {

    @Autowired
    private UserClient userClient;


    public abstract UserIdentifier.TypeDictItem getType();

    @Override
    public UserDetails loadUserByUsername(String identifier) throws UsernameNotFoundException {

        UserInnerDetailDto details = userClient.details(identifier, getType().name());
        if (details == null) {
            throw  new UsernameNotFoundException("identifier=["+ identifier +"],未获取到用户id");
        }
        return wrapperUserDetails(details);
    }

    public UserDetails wrapperUserDetails(UserInnerDetailDto details){

        String userId = details.getId();
        Set<String> authority = new HashSet<>();
        authority.add("user");
        List<String> roles = details.getRolesCode();
        List<String> funcs = details.getFuncsCode();
        boolean superAdmin = false;
        if (!isEmpty(roles)) {
            for (String role : roles) {
                if (isEqual(role, AbstractLoginUser.superadminCode)) {
                    superAdmin = true;
                    break;
                }
            }
            authority.addAll(roles.stream().map(role-> "ROLE_" + role).collect(Collectors.toSet()));
        }
        if (!isEmpty(funcs)) {
            authority.addAll(funcs);
        }
        List<RawDataConstraint> rawDataConstraints = details.getRawDataConstraint();

        LoginUser loginUser = new LoginUser(userId,
                details.getPwd(),
                true,
                true,
                true,
                !details.getIsLock(),
                AuthorityUtils.createAuthorityList(authority.toArray(new String[0])),
                rawDataConstraints
        );
        loginUser.setId(userId);
        loginUser.setSuperAdmin(superAdmin);
        loginUser.setIdentifierTypeDictId((String) details.getIdentifierTypeDictId());
        return loginUser;
    }
}
